﻿using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using TaskManager.Control;
using TaskManager.Event;
using UXTaskManager.Service;
using UXTaskManager.UI;

namespace UXTaskManager.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        #region Properties

        private string _text;

        public string Text
        {
            get { return _text; }
            set
            {
                if (_text == value)
                    return;

                _text = value;
                OnPropertyChanged("Text");
            }
        }

        private string _textToCopy;

        public string TextToCopy
        {
            get { return _textToCopy; }
            set
            {
                if (_textToCopy == value)
                    return;

                _textToCopy = value;
                OnPropertyChanged("TextToCopy");
            }
        }

        private DelegateCommand _startSimpleTaskCommand;

        private DelegateCommand _startTickTaskCommand;

        private DelegateCommand _startErrorTaskCommand;

        public TaskManagerViewModel TaskManager { get; private set; }

        private readonly IEventAggregator _eventAggregator;

        #endregion

        #region Constructor

        public MainViewModel()
        {
            var eventAggregator = (EventAggregator)ServiceLocator.Instance.GetService(typeof(IEventAggregator));
            _eventAggregator = eventAggregator;
            TaskManager = new TaskManagerViewModel(_eventAggregator);
        }

        #endregion

        #region Event

        public void OnTaskEventPublished(TaskEventArgs args)
        {
            if (args == null)
                return;

            switch (args.Type)
            {
                case TaskEventArgsType.Completed:
                    ShowPopup(args.TaskId);
                    break;
            }
        }

        private void ShowPopup(string id)
        {
            TaskViewModel task;
            if (TaskManager.TryGetTaskById(id, out task))
            {
                // TODO : Show popup here if you want
            }
        }

        #endregion

        #region Commands

        public ICommand StartSimpleTaskCommand
        {
            get
            {
                if (_startSimpleTaskCommand == null)
                {
                    _startSimpleTaskCommand = new DelegateCommand(StartSimpleTask, CanStartSimpleTask);
                }
                return _startSimpleTaskCommand;
            }
        }

        public ICommand StartTickTaskCommand
        {
            get
            {
                if (_startTickTaskCommand == null)
                {
                    _startTickTaskCommand = new DelegateCommand(StartTickTask, CanStartTickTask);
                }
                return _startTickTaskCommand;
            }
        }

        public ICommand StartErrorTaskCommand
        {
            get
            {
                if (_startErrorTaskCommand == null)
                {
                    _startErrorTaskCommand = new DelegateCommand(StartErrorTask, CanStartErrorTask);
                }
                return _startErrorTaskCommand;
            }
        }

        #endregion

        #region Actions

        #region Simple Task

        public bool CanStartSimpleTask()
        {
            return true;
        }

        /// <summary>
        /// Start a new simple task
        /// </summary>
        public void StartSimpleTask()
        {
            var textToCopy = TextToCopy;
            Func<object> beginAction = () =>
                                            {
                                                Thread.Sleep(1500);
                                                if (string.IsNullOrEmpty(textToCopy) || string.IsNullOrWhiteSpace(textToCopy))
                                                    return ":(";
                                                return textToCopy.ToUpper();
                                            };

            Action<Task<object>> endAction = (res) =>
                                                    {
                                                        Text = res.Result as string;
                                                    };

            var task = new TaskViewModel("Simple task !", beginAction, endAction);

            if (_eventAggregator != null)
                _eventAggregator.GetEvent<TaskEvent>().Publish(new TaskEventArgs(TaskEventArgsType.Started, task));
        }

        #endregion

        #region Tick Task

        public bool CanStartTickTask()
        {
            return true;
        }

        /// <summary>
        /// Start a new repetitive task
        /// </summary>
        public void StartTickTask()
        {
            if (_eventAggregator == null)
                return;

            var task = new TaskViewModel("Tick task !", null, null, null, false);

            Func<object> beginAction = () =>
            {
                Thread.Sleep(250);
                return true;
            };

            Action<Task<object>> endAction = (res) =>
            {
                Text = "Ok";
            };

            task.BeginAction = beginAction;
            task.EndAction = endAction;

            _eventAggregator.GetEvent<TaskEvent>().Publish(new TaskEventArgs(TaskEventArgsType.Started, task));

            var max = 50;
            for (var i = 0; i < max; i++)
            {
                _eventAggregator.GetEvent<TaskEvent>().Publish(
                    new TaskEventArgs(TaskEventArgsType.Updated, task.Id, (i * 100) / max));
            }

            _eventAggregator.GetEvent<TaskEvent>().Publish(
                        new TaskEventArgs(TaskEventArgsType.Ended, task.Id));
        }

        #endregion

        #region Error Task

        public bool CanStartErrorTask()
        {
            return true;
        }

        public void StartErrorTask()
        {
            Func<object> beginAction = () =>
            {
                Thread.Sleep(1500);
                throw new Exception("BOOM !");
            };

            Action<Task<object>> endAction = (res) =>
            {
                Text = "Ok";
            };

            var task = new TaskViewModel("Error task !", beginAction, endAction);

            if (_eventAggregator != null)
                _eventAggregator.GetEvent<TaskEvent>().Publish(new TaskEventArgs(TaskEventArgsType.Started, task));
        }

        #endregion

        #endregion
    }
}
